package com.lin.mytest.retry;

import lombok.extern.slf4j.Slf4j;
import org.springframework.retry.RetryException;
import org.springframework.retry.annotation.Backoff;
import org.springframework.retry.annotation.Recover;
import org.springframework.retry.annotation.Retryable;
import org.springframework.stereotype.Service;

/**
 * 重试的service方法
 *
 * @author lin
 * @since 2019年9月24日
 */
@Service
@Slf4j
public class RetryService {

    /**
     * 待重试的方法
     *
     * @param dto 重试传输dto
     * @author lin
     * @since 2019年9月24日
     * <p>
     * value：为指定重试的异常，只有该异常才会重试，如果多个异常重试，可以写做value = {RetryException.class,Exception.class}
     * maxAttempts: 为重试次数，默认为3次
     * Backeoff中的标签
     * delay: 延迟时间（单位为毫秒，默认为0毫秒）
     * multiplier：延迟间隔倍率，比如如果定义延迟为1秒，延迟倍率为2，则第一次重试间隔1秒，第二次2秒，第三次4秒，依次类推
     * maxDelay：最大间隔时间
     */
    @Retryable(value = RetryException.class, maxAttempts = 5, backoff = @Backoff(delay = 1000, multiplier = 2))
    public void handle(RetryTransferDto dto) {
        log.info("正在处理消息，当前次数第{}次，消息为{}", dto.getCount(), dto.getMessage());
        if (true) { // 模拟失败
            dto.setCount(dto.getCount() + 1);
            dto.setMessage(dto.getMessage() + " haha ");
            throw new RetryException("消息处理失败，当前次数第" + dto.getCount() + "次，消息为" + dto.getMessage());
        }
    }

    /**
     * 重试达到指定次数时，进入此方法
     *
     * @author lin
     * @since 2019年9月24日
     */
    @Recover
    public void recover(RetryException e) {
        log.error("重试达到指定测试", e);
    }
}
